import { h, defineComponent, markRaw, TransitionGroup, ref, computed } from 'vue'
import ContainerNode from '../../ItemNode/ContainerNode'
import classes from '../../ItemNode/ItemNode.module.css'
import { ElText, ElInput, ElForm, ElFormItem, ElButton } from 'element-plus'
import request from '../../request/request'
import requestRaw from '../../request/request?raw'

export default class NForm extends ContainerNode {
  isNForm = true
  isFormNode = true

  constructor(node?: NForm) {
    super(node)

    if (!node) {
      this.path = './components/NForm/NForm.tsx'
      this.name = '表单容器'

      const style = this.props.style
      this.props.style = {
        ...style,
        borderRadius: '5px'
      }

      this.props.submitUrl = ''
    }

    const pComponent = this.component
    this.component = markRaw(
      defineComponent(
        (props) => {
          const formRef = ref()
          const model = computed(() => {
            const data = {}

            this.traverse((node) => {
              if (node === this || !node.isFormNode) return

              data[node.props.field] = node.props.value
            })

            return data
          })

          const submitForm = (formEl) => {
            if (!formEl) return
            formEl.validate((valid) => {
              if (valid) {
                request({
                  url: this.props.submitUrl,
                  method: 'POST',
                  data: model.value
                })
              }
            })
          }

          return () => (
            <pComponent>
              <ElForm ref={formRef} model={model.value} label-width="auto">
                <TransitionGroup name="list">
                  {() => this.children.map((child, i) => h(child.component, { key: child.uuid }))}
                </TransitionGroup>
                {/* label=" " 解决控制台warn */}
                <ElFormItem label=" ">
                  <ElButton type="primary" onClick={() => submitForm(formRef.value)}>
                    提交
                  </ElButton>
                </ElFormItem>
              </ElForm>
            </pComponent>
          )
        },
        {
          name: 'NForm'
        }
      )
    )

    const pView = this.view
    this.view = markRaw(
      defineComponent((props) => {
        return () => <pView></pView>
      })
    )

    const pParams = this.params
    this.params = markRaw(
      defineComponent(() => {
        return () => (
          <pParams>
            <div class={classes['params-item']}>
              <ElText class={classes['params-item-label']} type="info">
                提交地址
              </ElText>
              <div class={classes['params-item-content']}>
                <ElInput v-model={this.props.submitUrl} size="small"></ElInput>
              </div>
            </div>
          </pParams>
        )
      })
    )
  }
  // 禁止嵌套表单
  checkChild(child) {
    let result = true

    if (!super.checkChild(child)) result = false

    child.traverse((node) => {
      if (node.isNForm) result = false
    })

    return result
  }

  toVue(): SfcObj {
    const sfcObj = super.toVue()
    const name = sfcObj.name
    const [uuid0, uuid1] = this.uuid.split('-')
    const formRefVar = `${name}_${uuid0}_ref`
    const modelVar = `${name}_${uuid0}_model`
    const submitVar = `${name}_${uuid0}_submit`

    let model = {}
    this.traverse((node) => {
      if (node === this || !node.isFormNode) return

      let name = node.constructor.name.replace(/^N(\w)/, (match, p1) => p1.toLowerCase())

      model[node.props.field] = `${name}_${node.uuid.split('-').at(0)}_value.value`
    })
    model = JSON.stringify(model).replaceAll('"', '')

    sfcObj.imports = {
      ...sfcObj.imports,
      vue: {
        computed: 'computed'
      },
      ['element-plus']: {
        ElForm: 'ElForm',
        ElFormItem: 'ElFormItem',
        ElInput: 'ElInput',
        ElButton: 'ElButton'
      },
      ['./imports/request.js']: {
        default: 'request'
      }
    }

    sfcObj.importFiles = {
      ...sfcObj.importFiles,
      'request.js': requestRaw
    }

    sfcObj.script = `
${sfcObj.script}
const ${formRefVar} = ref()
const ${modelVar} = computed(() => {
  return ${model}
})
const ${submitVar} = (formEl) => {
  if (!formEl) return
  formEl.validate((valid) => {
    if (valid) {
      request({
        url: '${this.props.submitUrl}',
        method: 'POST',
        data: ${modelVar}.value
      })
    }
  })
}
      `

    sfcObj.template = sfcObj.template.replace(
      '<slot></slot>',
      `
  <ElForm ref="${formRefVar}" :model="${modelVar}" label-width="auto">
    ${this.children.map((child) => child.uuid).join('\n    ')}
    <ElFormItem label=" ">
      <ElButton type="primary" @click="${submitVar}(${formRefVar})">
        提交
      </ElButton>
    </ElFormItem>
  </ElForm>
      `
    )

    return sfcObj
  }
}
